// src/store/service/index.ts
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { AppState } from "@store/index";
import { resetCredentials, saveCredentials } from "@slice/credentials";



// 定黑名单 不需要携带token的接口
const BlackList = ['login','sendMsgCode'];
// 自定义 baseQuery，全局注入 token
const request = fetchBaseQuery({
  baseUrl: process.env.REACT_APP_BASE_URL, 
  prepareHeaders: (headers, { getState, endpoint}) => {
    console.log(endpoint,'--->>')
    // 判断当前请求的接口是否在黑名单内
    const isIn = Array.isArray(BlackList) && BlackList.includes(endpoint);
    if (!isIn) {
      console.log(' 需要注入token')
      //不是请求的登录接口 需要注入token
      const state = getState() as AppState;
      const token = state.credentialsReducer.token;
      if (token) {
        headers.set('Authorization', `Bearer ${token}`);
      }
    }
    return headers;
  },
});
// 创建了一个全局的API状态切片
const apiService = createApi({
  reducerPath: "apiReducer",
  // baseQuery 选项实际上接收的是一个返回 Promise 对象的函数, 即异步函数
  baseQuery: async (args, api, extraOptions) => {
    // args: 对象类型, 存储的是开发者构建的请求对应的请求配置对象
    // api: 对象类型, 存储了 dispatch、getState 等方法
    // extraOptions: 构建请求时传递的自定义参数, 在 query 方法的返回值中通过 extraOptions 指定
    // 发送请求
    const response = await request(args, api, extraOptions);
    // 特别注意: 请求无论成功还是失败, Promsie 的状态都会变为 fulfilled
    // response -> 请求成功 -> { data: {}, meta: {} }
    // response -> 请求失败 -> { error: { status: 401, data: {} }, meta: {} }
    // 如果请求有错误并且错误状态码为401
    if (
      typeof response.error !== "undefined" &&
      response.error.status === 401
    ) {
      const { router } = require("@router/index");
      // 获取登录凭据对象
      const refresh_token = (api.getState() as AppState).credentialsReducer.refresh_token;
      // 获取当前页面路由信息, 为跳转做准备
      const { pathname, search, hash } = router.state.location;
      // 如果用于换取 token 的 refresh_token 存在
      if (refresh_token) {
        // 发送请求换取 token
        const response = await request(
          {
            url: "/authorizations",
            method: "put",
            headers: {
              authorization: `Bearer ${refresh_token}`,
            },
          },
          api,
          extraOptions
        );
        // 如果换取 token 成功
        if (typeof response.error === "undefined") {
          // 保存 token
          api.dispatch(
            saveCredentials({
              token: (response.data as GeekResponse<{ token: string }>).data
                .token,
              refresh_token: refresh_token,
            })
          );
          // 重新发送原始请求
          return request(args, api, extraOptions);
        } else {
          // token 换取失败
          api.dispatch(resetCredentials());
          // 跳转到登录页面
          router.navigate("/login", {
            state: { from: pathname + search + hash },
            replace: true,
          });
        }
      } else {
        // 跳转到登录页面
        router.navigate("/login", {
          state: { from: pathname + search + hash },
          replace: true,
        });
      }
    }
    return response;
  },
  endpoints: () => ({}),
});

export default apiService;

